package cn.edu.sgu.www.pms.service.impl;

import cn.edu.sgu.www.pms.dto.MenuTreeDTO;
import cn.edu.sgu.www.pms.dto.UserMenuDTO;
import cn.edu.sgu.www.pms.easyui.Tree;
import cn.edu.sgu.www.pms.entity.Menu;
import cn.edu.sgu.www.pms.entity.UserMenu;
import cn.edu.sgu.www.pms.mapper.MenuMapper;
import cn.edu.sgu.www.pms.mapper.RoleMenuMapper;
import cn.edu.sgu.www.pms.mapper.UserMenuMapper;
import cn.edu.sgu.www.pms.service.UserMenuService;
import cn.edu.sgu.www.pms.util.StringUtils;
import cn.edu.sgu.www.pms.util.UserUtils;
import cn.edu.sgu.www.pms.vo.MenuVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class UserMenuServiceImpl implements UserMenuService {

    private final MenuMapper menuMapper;
    private final RoleMenuMapper roleMenuMapper;
    private final UserMenuMapper userMenuMapper;

    @Autowired
    public UserMenuServiceImpl(
            MenuMapper menuMapper,
            RoleMenuMapper roleMenuMapper,
            UserMenuMapper userMenuMapper) {
        this.menuMapper = menuMapper;
        this.roleMenuMapper = roleMenuMapper;
        this.userMenuMapper = userMenuMapper;
    }

    @Override
    public void control(MenuTreeDTO menuTreeDTO) {
        String userId = UserUtils.getUserId();

        menuTreeDTO.setUserId(userId);

        display(menuTreeDTO);
    }

    @Override
    public void display(MenuTreeDTO menuTreeDTO) {
        List<String> displayIds = menuTreeDTO.getDisplayIds();
        List<String> hideIds = menuTreeDTO.getHideIds();
        String userId = menuTreeDTO.getUserId();

        // 创建应该临时的list，用来保存displayIds
        List<String> temp = new ArrayList<>(displayIds);

        // 两个list都不为空，去除两个list共有的元素
        if (!displayIds.isEmpty() && !hideIds.isEmpty()) {
            // 删除temp和hideIds共有的元素
            temp.removeIf(new Predicate<String>() {
                @Override
                public boolean test(String str) {
                    return hideIds.contains(str);
                }
            });

            // 删除hideIds和displayIds共有的元素
            List<String> finalDisplayIds = displayIds;

            hideIds.removeIf(new Predicate<String>() {
                @Override
                public boolean test(String str) {
                    return finalDisplayIds.contains(str);
                }
            });

            displayIds = temp;
        }

        // 显示操作
        if (!displayIds.isEmpty()) {
            for (String menuId : displayIds) {
                UpdateWrapper<UserMenu> updateWrapper = new UpdateWrapper<>();

                updateWrapper.eq("menu_id", menuId);
                updateWrapper.eq("user_id", userId);

                List<UserMenu> list = userMenuMapper.selectList(updateWrapper);

                // 查询结果为空，则添加用户菜单
                if (list.isEmpty()) {
                    UserMenu userMenu = new UserMenu();

                    userMenu.setId(null);
                    userMenu.setPxh(1000);
                    userMenu.setDisplay(true);
                    userMenu.setUserId(userId);
                    userMenu.setMenuId(menuId);

                    userMenuMapper.insert(userMenu);
                } else {
                    // 否则修改用户采的的display为1
                    updateWrapper.set("display", 1);

                    userMenuMapper.update(updateWrapper.getEntity(), updateWrapper);
                }
            }
        }

        // 隐藏操作
        if (!hideIds.isEmpty()) {
            // 修改用户菜单的display为0
            UpdateWrapper<UserMenu> updateWrapper = new UpdateWrapper<>();

            updateWrapper.in("menu_id", hideIds);
            updateWrapper.eq("user_id", userId);
            updateWrapper.set("display", 0);

            userMenuMapper.update(updateWrapper.getEntity(), updateWrapper);
        }
    }

    @Override
    public void setSort(String menuId, Integer pxh) {
        // 获取当前登录的用户的ID
        String userId = UserUtils.getUserId();

        UpdateWrapper<UserMenu> updateWrapper = new UpdateWrapper<>();

        updateWrapper.set("pxh", pxh);
        updateWrapper.eq("user_id", userId);
        updateWrapper.eq("menu_id", menuId);

        userMenuMapper.update(updateWrapper.getEntity(), updateWrapper);
    }

    @Override
    public void updateSort(UserMenuDTO userMenuDTO) {
        UpdateWrapper<UserMenu> updateWrapper = new UpdateWrapper<>();

        updateWrapper.set("pxh", userMenuDTO.getPxh());
        updateWrapper.eq("user_id", userMenuDTO.getUserId());
        updateWrapper.eq("menu_id", userMenuDTO.getMenuId());

        userMenuMapper.update(updateWrapper.getEntity(), updateWrapper);
    }

    @Override
    public List<MenuVO> selectLeftMenu() {
        // 获取用户ID
        String userId = UserUtils.getUserId();

        return getLeftMenu(userId);
    }

    @Override
    public List<Tree<Void>> selectMenuTree() {
        // 得到当前登录的用户ID
        String userId = UserUtils.getUserId();

        return getMenuTree(userId);
    }

    @Override
    public List<MenuVO> getLeftMenu(String userId) {
        List<MenuVO> result = new ArrayList<>();
        // 查询用户设置显示的菜单
        List<Menu> list = userMenuMapper.selectUserDisplayMenus(userId);

        if (!list.isEmpty()) {
            // 获取父菜单ID
            List<String> parentIds = list.stream().map(new Function<Menu, String>() {
                @Override
                public String apply(Menu menu) {
                    return menu.getParentId();
                }
            }).collect(Collectors.toList());

            // 查询父菜单
            QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();

            queryWrapper.in("id", parentIds);

            List<Menu> menus = menuMapper.selectList(queryWrapper);

            /*
             * 创建一个map保存父菜单ID和父菜单
             */
            Map<String, Menu> parentMap = new HashMap<>();

            /*
             * 创建一个map保存父菜单ID和子菜单列表
             */
            Map<String, List<Menu>> resultMap = new HashMap<>();

            for (Menu menu : menus) {
                String menuId = menu.getId();

                parentMap.put(menuId, menu);
                resultMap.put(menuId, new ArrayList<>());
            }

            for (Menu menu : list) {
                String parentId = menu.getParentId();

                resultMap.get(parentId).add(menu);
            }

            for (Map.Entry<String, List<Menu>> entry : resultMap.entrySet()) {
                String key = entry.getKey();
                Menu parent = parentMap.get(key);
                MenuVO menuVO = new MenuVO();

                menuVO.setId(parent.getId());
                menuVO.setName(parent.getName());
                menuVO.setIconClass(parent.getIconClass());

                List<MenuVO> children = new ArrayList<>();
                int pxh = 0;

                for (Menu menu : entry.getValue()) {
                    if (pxh == 0 || pxh > menu.getPxh()) {
                        pxh = menu.getPxh();
                    }

                    MenuVO child = new MenuVO();

                    child.setId(menu.getId());
                    child.setPxh(menu.getPxh());
                    child.setName(menu.getName());
                    child.setUrl(menu.getUrl());
                    child.setIconClass(menu.getIconClass());

                    children.add(child);
                }

                menuVO.setPxh(pxh);
                menuVO.setChildren(children);

                result.add(menuVO);
            }

            // 按照父菜单的排序号排序
            result.sort(new Comparator<MenuVO>() {
                @Override
                public int compare(MenuVO o1, MenuVO o2) {
                    return o1.getPxh() - o2.getPxh();
                }
            });
        }

        return result;
    }

    @Override
    public List<Tree<Void>> getMenuTree(String userId) {
        // 查询当前用户绑定角色的所有子菜单
        List<Menu> userMenus = roleMenuMapper.selectRoleMenus(userId);

        /*
         * 构建map，以parentId为key，子菜单列表为value保存菜单信息
         */
        Map<String, List<Menu>> resultMap = new LinkedHashMap<>();

        // 通过stream流获取所有用户菜单的父菜单ID
        List<String> parentIds = userMenus.stream().map(new Function<Menu, String>() {
            @Override
            public String apply(Menu menu) {
                String parentId = menu.getParentId();

                if (StringUtils.isNotEmpty(parentId)) {
                    // 把父菜单ID作为key保存到parentMap
                    resultMap.put(parentId, new ArrayList<>());

                    return parentId;
                }

                return null;
            }
        }).collect(Collectors.toList());

        // 父菜单ID列表不为空才构建菜单树
        if (!parentIds.isEmpty()) {
            // 查询所有父菜单信息
            QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();

            queryWrapper.in("id", parentIds);

            List<Menu> parentMenus = menuMapper.selectList(queryWrapper);

            /*
             * 构建map，以菜单为key，菜单信息为value保存父菜单信息
             */
            Map<String, String> parentMap = new HashMap<>();

            for (Menu menu : parentMenus) {
                parentMap.put(menu.getId(), menu.getName());
            }

            /*
             * 构建map，以菜单ID为key，菜单信息为value保存所有菜单信息
             */
            Map<String, Menu> menuMap = new HashMap<>();

            for (Menu menu : userMenus) {
                String menuId = menu.getId();

                if (!menuMap.containsKey(menuId)) {
                    menuMap.put(menuId, menu);
                }

                String parentId = menu.getParentId();
                List<Menu> menus = resultMap.get(parentId);

                if (menus != null) {
                    menus.add(menu);
                } else {
                    List<Menu> list = new ArrayList<>();

                    list.add(menu);

                    resultMap.put(parentId, list);
                }
            }

            /*
             * 构建返回值对象
             */
            List<Tree<Void>> result = new ArrayList<>();

            for (Map.Entry<String, List<Menu>> entry : resultMap.entrySet()) {
                String key = entry.getKey(); // map的key就是parentId
                Tree<Void> parent = new Tree<>();

                parent.setId(key);
                parent.setState("open");
                parent.setText(parentMap.get(key));
                // menuTree.setChecked(true); // 父节点不设置选中状态，根据子节点的选中状态动态显示

                List<Tree<Void>> children = new ArrayList<>();

                for (Menu menu : entry.getValue()) {
                    Tree<Void> child = new Tree<>();

                    child.setId(menu.getId());
                    child.setPxh(menu.getPxh());
                    child.setText(menu.getName());
                    child.setChecked(menu.isDisplay());

                    children.add(child);
                }

                parent.setChildren(children);

                result.add(parent);
            }

            return result;
        }

        return new ArrayList<>();
    }

}